// 引入必要的头文件
#include <ros/ros.h> // ROS基础功能头文件
#include <actionlib/server/simple_action_server.h> // 动作服务器库
#include <action_communication/setarpAction.h> // 自定义动作消息类型头文件

// 定义动作服务器类型别名，简化后续代码
typedef actionlib::SimpleActionServer<action_communication::setarpAction> Server;

// 动作服务器类定义
class ActionServer {
public:
    // 构造函数初始化动作服务器
    ActionServer(ros::NodeHandle &nh) : 
        // 初始化服务器对象，参数依次为节点句柄、动作名称、回调函数、是否自动启动
        server_(nh, "action", boost::bind(&ActionServer::cb, this, _1, &server_), false) 
        {
            server_.start(); // 显式启动服务器（当auto_start设为false时需要）
        }
        // 动作请求回调函数（核心业务逻辑）
        void cb(const action_communication::setarpGoalConstPtr &goal_ptr, Server* server) 
        {
            int goal = goal_ptr->goal; // 从目标请求中提取目标值
            // 输入验证：目标值必须为正数
            if (goal <= 0) 
            {  
                action_communication::setarpResult r;
                r.result = false;
                // 设置动作为中止状态，返回错误信息和结果
                server->setAborted(r, "Invalid goal value");
                return;
            }
            ros::Rate rate(1); // 创建1Hz的速率控制器
            int result = 0;
            // 模拟处理过程的主循环
            for (result=1; result <= goal; result++) 
            {
                rate.sleep(); // 维持1Hz频率
                // 创建并填充反馈消息
                action_communication::setarpFeedback fb;
                fb.progress_bar = (double)result/goal * 100; // 计算完成百分比           
                // 发布进度反馈给客户端
                server->publishFeedback(fb);
            }
            result--;  // 修正循环结束后的结果值（最后一次循环后result=goal+1）
            rate.sleep(); // 最后一次延时确保完成      
            // 设置动作结果为成功
            action_communication::setarpResult r;
            r.result = (result == goal); // 验证最终结果是否匹配目标
            server->setSucceeded(r); // 发送成功状态和结果        
            ROS_INFO("检测到%d个零件", result); // 输出结果日志
        }
    private:
    Server server_; // 动作服务器对象
};

int main(int argc, char *argv[])
{
    setlocale(LC_ALL, ""); // 设置本地化支持中文输出

    // ROS节点初始化
    ros::init(argc, argv, "service_action"); // 节点名称为service_action
    ros::NodeHandle nh;
    
    // 创建动作服务器对象
    ActionServer as(nh);
    
    ros::spin(); // 进入事件循环等待请求
    
    return 0;
}